﻿using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Web;

namespace ImageService
{
    public class CarImageServer
    {
        private TcpListener _listener;
        private int _port;
        private string _path;

        /// <summary>
        /// 初始化图片服务器
        /// </summary>
        /// <param name="port"></param>
        /// <param name="path"></param>
        public CarImageServer(int port, string path)
        {
            _port = port;
            _path = path;
        }

        public bool Start()
        {
            bool status = true;
            try
            {
                _listener = new TcpListener(IPAddress.Any, _port);
                _listener.Start();
                // 启动监听线程
                Thread th = new Thread(new ThreadStart(StartListen));
                th.Start();
                return status;
            }
            catch (Exception)
            {
                _listener.Stop();
                return false;
            }
        }

        private void StartListen()
        {
            int iStartPos = 0;
            String sRequest;
            String sDirName;
            String sRequestedFile;
            String sErrorMessage;
            String sLocalDir;
            String sPhysicalFilePath = "";
            String sResponse = "";

            while (true)
            {
                //接受新连接
                Socket mySocket = this._listener.AcceptSocket();
                if (mySocket.Connected)
                {
                    Byte[] bReceive = new Byte[1024];
                    int i = mySocket.Receive(bReceive, bReceive.Length, 0);
                    //转换成字符串类型
                    string sBuffer = HttpUtility.UrlDecode(Encoding.ASCII.GetString(bReceive));
                    //只处理GET类型请求
                    if (sBuffer.Substring(0, 3) != "GET")
                    {
                        mySocket.Close();
                        continue;
                    }
                    // 查找 "HTTP" 的位置
                    iStartPos = sBuffer.IndexOf("HTTP", 1);
                    string sHttpVersion = sBuffer.Substring(iStartPos, 8);
                    // 得到请求类型和文件目录文件名
                    sRequest = sBuffer.Substring(0, iStartPos - 1);
                    sRequest.Replace("\\", "/");
                    //如果结尾不是文件名也不是以"/"结尾则加"/"
                    if ((sRequest.IndexOf(".") < 1) && (!sRequest.EndsWith("/")))
                    {
                        sRequest = sRequest + "/";
                    }
                    //得带请求文件名
                    iStartPos = sRequest.LastIndexOf("/") + 1;
                    sRequestedFile = sRequest.Substring(iStartPos);
                    //得到请求文件目录
                    sDirName = sRequest.Substring(sRequest.IndexOf("/"), sRequest.LastIndexOf("/") - 3);
                    //获取虚拟目录物理路径
                    sLocalDir = this._path;
                    if (sLocalDir.Length == 0)
                    {
                        sErrorMessage = "请求的路径不存在";
                        SendHeader(sHttpVersion, "", sErrorMessage.Length, " 404 Not Found", ref mySocket);
                        SendToBrowser(sErrorMessage, ref mySocket);
                        mySocket.Close();
                        continue;
                    }
                    if (sRequestedFile.Length == 0)
                    {
                        // 取得请求文件名
                        sRequestedFile = "default.jpg";
                    }

                    sPhysicalFilePath = sLocalDir + "\\" + sRequestedFile;
                    if (!File.Exists(sPhysicalFilePath))
                    {
                        sErrorMessage = "未找到图片文件";
                        SendHeader(sHttpVersion, "", sErrorMessage.Length, " 404 Not Found", ref mySocket);
                        SendToBrowser(sErrorMessage, ref mySocket);
                    }
                    else
                    {
                        int iTotBytes = 0;
                        String sMimeType = "image/jpeg";
                        sResponse = "";
                        FileStream fs = new FileStream(sPhysicalFilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
                        BinaryReader reader = new BinaryReader(fs);
                        byte[] bytes = new byte[fs.Length];
                        int read;
                        while ((read = reader.Read(bytes, 0, bytes.Length)) != 0)
                        {
                            sResponse = sResponse + Encoding.ASCII.GetString(bytes, 0, read);
                            iTotBytes = iTotBytes + read;
                        }
                        reader.Close();
                        fs.Close();
                        SendHeader(sHttpVersion, sMimeType, iTotBytes, " 200 OK", ref mySocket);
                        SendToBrowser(bytes, ref mySocket);
                    }
                    mySocket.Close();
                }
            }
        }

        private void SendHeader(string sHttpVersion, string sMIMEHeader, int iTotBytes, string sStatusCode, ref Socket mySocket)
        {
            String sBuffer = "";
            if (sMIMEHeader.Length == 0)
            {
                sMIMEHeader = "text/html; charset=utf-8";
            }
            sBuffer = sBuffer + sHttpVersion + sStatusCode + "\r\n";
            sBuffer = sBuffer + "Server: Parkgo-1.0\r\n";
            sBuffer = sBuffer + "Content-Type: " + sMIMEHeader + "\r\n";
            sBuffer = sBuffer + "Accept-Ranges: bytes\r\n";
            sBuffer = sBuffer + "Content-Length: " + iTotBytes + "\r\n\r\n";
            Byte[] bSendData = Encoding.UTF8.GetBytes(sBuffer);
            SendToBrowser(bSendData, ref mySocket);
        }

        public void SendToBrowser(String sData, ref Socket mySocket)
        {
            SendToBrowser(Encoding.ASCII.GetBytes(sData), ref mySocket);
        }

        public void SendToBrowser(Byte[] bSendData, ref Socket mySocket)
        {
            int numBytes = 0;
            try
            {
                if (mySocket.Connected)
                {
                    numBytes = mySocket.Send(bSendData, bSendData.Length, 0);
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }


    }
}
